home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-10-24 | 48.2 KB | 2,426 lines |
- Newsgroups: comp.sources.misc
- From: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
- Subject: v24i006: zsh2.1 - The Z shell, Part06/19
- Message-ID: <1991Oct24.190840.25712@sparky.imd.sterling.com>
- X-Md4-Signature: 01c07cafb955e10e801560c9c5869f5c
- Date: Thu, 24 Oct 1991 19:08:40 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: pfalstad@phoenix.Princeton.EDU (Paul Falstad)
- Posting-number: Volume 24, Issue 6
- Archive-name: zsh2.1/part06
- Environment: BSD
- Supersedes: zsh2.00: Volume 18, Issue 84-98
-
- #!/bin/sh
- # this is zshar.06 (part 6 of zsh2.1.0)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file zsh2.1/src/exec.c continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 6; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping zsh2.1/src/exec.c'
- else
- echo 'x - continuing file zsh2.1/src/exec.c'
- sed 's/^X//' << 'SHAR_EOF' >> 'zsh2.1/src/exec.c' &&
- X blockchld();
- X if ((thisjob = getfreejob()) == -1)
- X return 1;
- X initjob();
- X if (how == TIMED)
- X {
- X jobtab[thisjob].stat |= STAT_TIMED;
- X how = SYNC;
- X }
- X if (l->flags & PFLAG_COPROC)
- X {
- X how = ASYNC;
- X mpipe(ipipe);
- X mpipe(opipe);
- X if (coprocin)
- X {
- X close(coprocin);
- X close(coprocout);
- X }
- X coprocin = ipipe[0];
- X coprocout = opipe[1];
- X }
- X execpline2(l->left,how,opipe[0],ipipe[1],last1);
- X if (how == ASYNC)
- X {
- X spawnjob();
- X unblockchld();
- X return 1;
- X }
- X else
- X {
- X waitjobs();
- X unblockchld();
- X if (l->flags & PFLAG_NOT)
- X lastval = !lastval;
- X return !lastval;
- X }
- X}
- X
- Xvoid execpline2(pline,how,input,output,last1) /**/
- XPline pline;int how;int input;int output;int last1;
- X{
- Xint pid;
- Xint pipes[2];
- X
- X if (breaks)
- X return;
- X if (!pline)
- X return;
- X if (pline->type == END)
- X {
- X execcmd(pline->left,input,output,how==ASYNC,last1);
- X pline->left = NULL;
- X }
- X else
- X {
- X mpipe(pipes);
- X
- X /* if we are doing "foo | bar" where foo is a current
- X shell command, do foo in the current shell and do
- X the rest of the pipeline in a subshell. */
- X
- X if (pline->left->type >= CURSH && how == SYNC)
- X {
- X if (!(pid = fork()))
- X {
- X close(pipes[1]);
- X entersubsh(how==ASYNC);
- X exiting = 1;
- X execpline2(pline->right,ASYNC,pipes[0],output,1);
- X _exit(lastval);
- X }
- X else if (pid == -1)
- X zerr("fork failed: %e",NULL,errno);
- X else
- X {
- X char *s,*text;
- X
- X close(pipes[0]);
- X text = s = gettext((vptr) pline->right,0);
- X addproc(pid,text)->lastfg = 1;
- X pline->right = NULL;
- X }
- X }
- X
- X /* otherwise just do the pipeline normally. */
- X
- X execcmd(pline->left,input,pipes[1],how==ASYNC,0);
- X pline->left = NULL;
- X close(pipes[1]);
- X if (pline->right)
- X {
- X execpline2(pline->right,how,pipes[0],output,last1);
- X close(pipes[0]);
- X }
- X }
- X}
- X
- X/* make the argv array */
- X
- Xchar **makecline(list) /**/
- Xstruct lklist *list;
- X{
- Xint ct = 0;
- XLknode node;
- Xchar **argv,**ptr;
- X
- X if (isset(XTRACE))
- X {
- X fprintf(stderr,"%s",(prompt4) ? prompt4 : "");
- X for (node = firstnode(list); node; incnode(node),ct++);
- X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
- X for (node = firstnode(list); node; incnode(node))
- X if (*(char *) getdata(node))
- X {
- X *ptr++ = getdata(node);
- X untokenize(getdata(node));
- X fputs(getdata(node),stderr);
- X if (nextnode(node))
- X fputc(' ',stderr);
- X }
- X *ptr = NULL;
- X fputc('\n',stderr);
- X fflush(stderr);
- X return(argv);
- X }
- X else
- X {
- X for (node = firstnode(list); node; incnode(node),ct++);
- X ptr = argv = 2+(char **) ncalloc((ct+4)*sizeof(char *));
- X for (node = firstnode(list); node; incnode(node))
- X if (*(char *) getdata(node))
- X {
- X *ptr++ = getdata(node);
- X untokenize(getdata(node));
- X }
- X *ptr = NULL;
- X return(argv);
- X }
- X}
- X
- X/* untokenize the command line and remove null arguments */
- X
- Xvoid fixcline(l) /**/
- XLklist l;
- X{
- XLknode node,next;
- X
- X for (node = firstnode(l); node; node = next)
- X {
- X next = nextnode(node);
- X if (!*(char *) getdata(node))
- X uremnode(l,node);
- X else
- X untokenize(getdata(node));
- X }
- X}
- X
- Xvoid untokenize(s) /**/
- Xchar *s;
- X{
- X for (; *s; s++)
- X if (itok(*s))
- X if (*s == Nularg)
- X chuck(s--);
- X else
- X *s = ztokens[*s-Pound];
- X}
- X
- X/* nonzero if we shouldn't clobber a file */
- X
- Xint dontclob(f) /**/
- Xstruct redir *f;
- X{
- Xstruct stat buf;
- X
- X if (unset(NOCLOBBER) || f->type & 1)
- X return 0;
- X if (stat(f->name,&buf) == -1)
- X return 1;
- X return S_ISREG(buf.st_mode);
- X}
- X
- X/* close an multio (success) */
- X
- Xvoid closemn(mfds,fd) /**/
- Xstruct multio **mfds;int fd;
- X{
- X if (mfds[fd])
- X {
- X if (mfds[fd]->ct > 1)
- X if (mfds[fd]->rflag == 0)
- X catproc(mfds[fd]);
- X else
- X teeproc(mfds[fd]);
- X mfds[fd] = NULL;
- X }
- X}
- X
- X/* close all the mnodes (failure) */
- X
- Xvoid closemnodes(mfds) /**/
- Xstruct multio **mfds;
- X{
- Xint t0,t1;
- X
- X for (t0 = 0; t0 != 10; t0++)
- X if (mfds[t0])
- X {
- X for (t1 = 0; t1 != mfds[t0]->ct; t1++)
- X close(mfds[t0]->fds[t1]);
- X mfds[t0] = NULL;
- X }
- X}
- X
- X/* add a fd to an multio */
- X/* an multio is a list of fds associated with a certain fd.
- X thus if you do "foo >bar >ble", the multio for fd 1 will have
- X two fds, the result of open("bar",...), and the result of
- X open("ble",....). */
- X
- Xvoid addfd(forked,save,mfds,fd1,fd2,rflag) /**/
- Xint forked;int *save;struct multio **mfds;int fd1;int fd2;int rflag;
- X{
- Xint pipes[2];
- X
- X if (!mfds[fd1]) /* starting a new multio */
- X {
- X mfds[fd1] = (struct multio *) alloc(sizeof(struct multio));
- X if (!forked && fd1 != fd2 && fd1 < 10)
- X save[fd1] = movefd(fd1);
- X redup(fd2,fd1);
- X mfds[fd1]->ct = 1;
- X mfds[fd1]->fds[0] = fd1;
- X mfds[fd1]->rflag = rflag;
- X }
- X else
- X {
- X if (mfds[fd1]->rflag != rflag)
- X {
- X zerr("file mode mismatch on fd %d",NULL,fd1);
- X return;
- X }
- X if (mfds[fd1]->ct == 1) /* split the stream */
- X {
- X mfds[fd1]->fds[0] = movefd(fd1);
- X mfds[fd1]->fds[1] = movefd(fd2);
- X mpipe(pipes);
- X mfds[fd1]->pipe = pipes[1-rflag];
- X redup(pipes[rflag],fd1);
- X mfds[fd1]->ct = 2;
- X }
- X else /* add another fd to an already split stream */
- X mfds[fd1]->fds[mfds[fd1]->ct++] = movefd(fd2);
- X }
- X}
- X
- Xvoid addvars(l,export) /**/
- XLklist l;int export;
- X{
- Xstruct varasg *v;
- XLklist vl;
- X
- X while (full(l))
- X {
- X char **arr,**ptr;
- X
- X v = (struct varasg *) ugetnode(l);
- X singsub(&v->name);
- X if (errflag)
- X return;
- X untokenize(v->name);
- X if (v->type == PMFLAG_s)
- X {
- X vl = newlist();
- X addnode(vl,v->str);
- X }
- X else
- X vl = v->arr;
- X prefork(vl);
- X if (errflag)
- X return;
- X postfork(vl,1);
- X if (errflag)
- X return;
- X if (v->type == PMFLAG_s && (!full(vl) || !nextnode(firstnode(vl))))
- X {
- X Param pm;
- X char *val;
- X
- X if (!full(vl))
- X pm = setsparam(v->name,val = ztrdup(""));
- X else
- X {
- X untokenize(peekfirst(vl));
- X pm = setsparam(v->name,val = ztrdup(ugetnode(vl)));
- X }
- X if (export && !(pm->flags & PMFLAG_x))
- X addenv(v->name,val);
- X continue;
- X }
- X ptr = arr = (char **) zalloc(sizeof(char **)*(countnodes(vl)+1));
- X while (full(vl))
- X {
- X *ptr = ztrdup(ugetnode(vl));
- X untokenize(*ptr++);
- X }
- X *ptr = NULL;
- X setaparam(v->name,arr);
- X }
- X}
- X
- Xvoid execcmd(cmd,input,output,bkg,last1) /**/
- XCmd cmd;int input;int output;int bkg;int last1;
- X{
- Xint type;
- Xlong pid = 0;
- XLklist args = cmd->args;
- Xint save[10],t0;
- Xstruct redir *fn;
- Xstruct multio *mfds[10];
- Xint fil,forked = 0,iscursh = 0,nullexec = 0;
- XCmdnam chn = NULL;
- Xchar *text;
- X
- X for (t0 = 0; t0 != 10; t0++)
- X {
- X save[t0] = 0;
- X mfds[t0] = NULL;
- X }
- X if ((type = cmd->type) == SIMPLE && !full(args))
- X if (full(cmd->redir))
- X if (cmd->flags & CFLAG_EXEC)
- X nullexec = 1;
- X else if (!*nullcmd)
- X {
- X zerr("redirection with no command",NULL,0);
- X errflag = lastval = 1;
- X return;
- X }
- X else
- X addnode(args,strdup(nullcmd));
- X else
- X {
- X addvars(cmd->vars,0);
- X return;
- X }
- X if (full(args) && *(char *) peekfirst(args) == '%')
- X {
- X insnode(args,(Lknode) args,strdup((bkg) ? "bg" : "fg"));
- X bkg = 0;
- X }
- X if (isset(AUTORESUME) && !bkg && !full(cmd->redir) && full(args) &&
- X !input && type == SIMPLE && !nextnode(firstnode(args)) &&
- X findjobnam(peekfirst(args)) != -1)
- X pushnode(args,strdup("fg"));
- X if (unset(RMSTARSILENT) && interact && isset(SHINSTDIN) &&
- X type == SIMPLE && full(args) && nextnode(firstnode(args)) &&
- X !strcmp(peekfirst(args),"rm"))
- X {
- X char *s = getdata(nextnode(firstnode(args)));
- X
- X if (s[0] == Star && !s[1])
- X checkrmall();
- X }
- X if (jobbing) /* get the text associated with this command */
- X {
- X char *s;
- X s = text = gettext((vptr) cmd,0);
- X }
- X else
- X text = NULL;
- X prefork(args); /* do prefork substitutions */
- X if (errflag)
- X {
- X lastval = 1;
- X return;
- X }
- X if (full(args) && ((char*)peekfirst(args))[0] == Inbrack &&
- X ((char*)peekfirst(args))[1] == '\0')
- X ((char*)peekfirst(args))[0] = '[';
- X if (full(args) && !(cmd->flags & CFLAG_COMMAND))
- X chn = (Cmdnam) gethnode(peekfirst(args),cmdnamtab);
- X if (type == SIMPLE && !pathsuppress && !chn && isset(AUTOCD) &&
- X full(args) && !full(cmd->redir) &&
- X !nextnode(firstnode(args)) && cancd(peekfirst(args)))
- X {
- X pushnode(args,strdup("cd"));
- X chn = (Cmdnam) gethnode("cd",cmdnamtab);
- X }
- X
- X /* this is nonzero if cmd is a current shell procedure */
- X
- X iscursh = (type >= CURSH) || (type == SIMPLE && chn &&
- X (chn->type == BUILTIN || chn->type == SHFUNC));
- X
- X /* if this command is backgrounded or (this is an external
- X command and we are not exec'ing it) or this is a builtin
- X with output piped somewhere, then fork. If this is the
- X last stage in a subshell pipeline, don't fork, but make
- X the rest of the function think we forked. */
- X
- X if (bkg || !(iscursh || (cmd->flags & CFLAG_EXEC)) ||
- X (chn && (chn->type == BUILTIN || chn->type == SHFUNC) && output))
- X {
- X int synch[2];
- X
- X pipe(synch);
- X pid = (last1 && execok()) ? 0 : phork();
- X if (pid == -1)
- X {
- X close(synch[0]);
- X close(synch[1]);
- X return;
- X }
- X if (pid)
- X {
- X close(synch[1]);
- X read(synch[0],"foo",1);
- X close(synch[0]);
- X if (pid == -1)
- X zerr("%e",NULL,errno);
- X else
- X ( void ) addproc(pid,text);
- X return;
- X }
- X close(synch[0]);
- X entersubsh(bkg);
- X close(synch[1]);
- X forked = 1;
- X }
- X if (bkg && isset(BGNICE)) /* stupid */
- X nice(5);
- X if (input) /* add pipeline input/output to mnodes */
- X addfd(forked,save,mfds,0,input,0);
- X if (output)
- X addfd(forked,save,mfds,1,output,1);
- X spawnpipes(cmd->redir); /* do process substitutions */
- X while (full(cmd->redir))
- X if ((fn = (struct redir*) ugetnode(cmd->redir))->type == INPIPE)
- X {
- X if (fn->fd2 == -1)
- X execerr();
- X addfd(forked,save,mfds,fn->fd1,fn->fd2,0);
- X }
- X else if (fn->type == OUTPIPE)
- X {
- X if (fn->fd2 == -1)
- X execerr();
- X addfd(forked,save,mfds,fn->fd1,fn->fd2,1);
- X }
- X else
- X {
- X if (!(fn->type == HERESTR || fn->type == CLOSE || fn->type ==
- X MERGE || fn->type == MERGEOUT))
- X if (xpandredir(fn,cmd->redir))
- X continue;
- X if (fn->type == HERESTR)
- X {
- X fil = getherestr(fn);
- X if (fil == -1)
- X {
- X if (errno != EINTR)
- X zerr("%e",NULL,errno);
- X execerr();
- X }
- X addfd(forked,save,mfds,fn->fd1,fil,0);
- X }
- X else if (fn->type == READ)
- X {
- X fil = open(fn->name,O_RDONLY);
- X if (fil == -1)
- X {
- X if (errno != EINTR)
- X zerr("%e: %s",fn->name,errno);
- X execerr();
- X }
- X addfd(forked,save,mfds,fn->fd1,fil,0);
- X }
- X else if (fn->type == CLOSE)
- X {
- X if (!forked && fn->fd1 < 10)
- X save[fn->fd1] = movefd(fn->fd1);
- X closemn(mfds,fn->fd1);
- X close(fn->fd1);
- X }
- X else if (fn->type == MERGE || fn->type == MERGEOUT)
- X {
- X fil = dup(fn->fd2);
- X if (mfds[fn->fd1])
- X redup(fil,fn->fd1);
- X else
- X addfd(forked,save,mfds,fn->fd1,fil,fn->type == MERGEOUT);
- X }
- X else
- X {
- X if (fn->type >= APP)
- X fil = open(fn->name,isset(NOCLOBBER) ?
- X O_WRONLY|O_APPEND : O_WRONLY|O_APPEND|O_CREAT,0666);
- X else
- X fil = open(fn->name,dontclob(fn) ?
- X O_WRONLY|O_CREAT|O_EXCL : O_WRONLY|O_CREAT|O_TRUNC,0666);
- X if (fil == -1)
- X {
- X if (errno != EINTR)
- X zerr("%e: %s",fn->name,errno);
- X execerr();
- X }
- X addfd(forked,save,mfds,fn->fd1,fil,1);
- X }
- X }
- X /* perform postfork substitutions */
- X /* you put this here so that ls *.sdfoij >& /dev/null works, remember? */
- X postfork(args,!(cmd->flags & CFLAG_NOGLOB));
- X if (errflag)
- X {
- X lastval = 1;
- X goto err;
- X }
- X
- X /* we are done with redirection. close the mnodes, spawning
- X tee/cat processes as necessary. */
- X for (t0 = 0; t0 != 10; t0++)
- X closemn(mfds,t0);
- X
- X if (nullexec)
- X return;
- X if (unset(NOEXEC))
- X if (type >= ZCTIME)
- X {
- X static int (*func[]) DCLPROTO((Cmd)) = {
- X exectime,execcursh,execfuncdef,execfor,execwhile,
- X execrepeat,execif,execcase,execselect,execcond };
- X
- X fixcline(args);
- X lastval = (func[type-ZCTIME])(cmd);
- X }
- X else if (iscursh) /* builtin or shell function */
- X {
- X if (cmd->vars)
- X addvars(cmd->vars,0);
- X fixcline(args);
- X if (chn && chn->type == SHFUNC)
- X execshfunc(cmd,chn);
- X else
- X {
- X lastval = execbin(args,chn);
- X if (isset(PRINTEXITVALUE) && lastval)
- X zerr("exit %d",NULL,lastval);
- X fflush(stdout);
- X if (ferror(stdout))
- X {
- X zerr("write error: %e",NULL,errno);
- X clearerr(stdout);
- X }
- X }
- X }
- X else
- X {
- X if (cmd->vars)
- X addvars(cmd->vars,1);
- X if (type == SIMPLE)
- X {
- X closem();
- X execute(args,cmd->flags & CFLAG_DASH);
- X }
- X else /* ( ... ) */
- X execlist(cmd->u.list);
- X }
- Xerr:
- X if (forked)
- X _exit(lastval);
- X fixfds(save);
- X}
- X
- X/* restore fds after redirecting a builtin */
- X
- Xvoid fixfds(save) /**/
- Xint *save;
- X{
- Xint t0;
- X
- X for (t0 = 0; t0 != 10; t0++)
- X if (save[t0])
- X redup(save[t0],t0);
- X}
- X
- Xvoid entersubsh(bkg) /**/
- Xint bkg;
- X{
- X if (!jobbing)
- X {
- X if (bkg && isatty(0))
- X {
- X close(0);
- X if (open("/dev/null",O_RDWR))
- X {
- X zerr("can't open /dev/null: %e",NULL,errno);
- X _exit(1);
- X }
- X }
- X }
- X else if (!jobtab[thisjob].gleader)
- X {
- X jobtab[thisjob].gleader = getpid();
- X setpgrp(0L,jobtab[thisjob].gleader);
- X if (!bkg)
- X attachtty(jobtab[thisjob].gleader);
- X }
- X else
- X setpgrp(0L,jobtab[thisjob].gleader);
- X subsh = 1;
- X if (SHTTY != -1)
- X {
- X close(SHTTY);
- X SHTTY = -1;
- X }
- X if (jobbing)
- X {
- X signal(SIGTTOU,SIG_DFL);
- X signal(SIGTTIN,SIG_DFL);
- X signal(SIGTSTP,SIG_DFL);
- X signal(SIGPIPE,SIG_DFL);
- X }
- X if (interact)
- X {
- X signal(SIGTERM,SIG_DFL);
- X if (sigtrapped[SIGINT])
- X signal(SIGINT,SIG_IGN);
- X }
- X if (!sigtrapped[SIGQUIT])
- X signal(SIGQUIT,SIG_DFL);
- X opts[MONITOR] = OPT_UNSET;
- X clearjobtab();
- X}
- X
- X/* close all internal shell fds */
- X
- Xvoid closem() /**/
- X{
- Xint t0;
- X
- X for (t0 = 10; t0 != NOFILE; t0++)
- X close(t0);
- X}
- X
- X/* convert here document into a here string */
- X
- Xchar *gethere(str,typ) /**/
- Xchar *str;int typ;
- X{
- Xchar pbuf[256];
- Xint qt = 0,siz = 0,l,strip = 0;
- Xchar *s,*t,*bptr;
- X
- X for (s = str; *s; s++)
- X if (*s == Nularg)
- X qt = 1;
- X untokenize(str);
- X if (typ == HEREDOCDASH)
- X {
- X strip = 1;
- X while (*str == '\t')
- X str++;
- X }
- X t = ztrdup("");
- X for(;;)
- X {
- X char *u,*v;
- X
- X if (!fgets(pbuf,256,bshin))
- X break;
- X bptr = pbuf;
- X if (strip)
- X while (*bptr == '\t')
- X bptr++;
- X for (u = bptr, v = str; *u != '\n' && *v; u++,v++)
- X if (*u != *v)
- X break;
- X if (!(*u == '\n' && !*v))
- X {
- X l = strlen(bptr);
- X if (!qt && l > 1 && bptr[l-1] == '\n' && bptr[l-2] == '\\')
- X bptr[l -= 2] = '\0';
- X t = realloc(t,siz+l+1);
- X strncpy(t+siz,bptr,l);
- X siz += l;
- X }
- X else
- X break;
- X }
- X t[siz] = '\0';
- X if (siz && t[siz-1] == '\n')
- X t[siz-1] = '\0';
- X if (!qt)
- X for (s = t; *s; s++)
- X if (*s == '$')
- X *s = Qstring;
- X else if (*s == '`')
- X *s = Qtick;
- X else if (*s == '\\')
- X {
- X s++;
- X if (!*s)
- X break;
- X }
- X s = strdup(t);
- X free(t);
- X return s;
- X}
- X
- X/* open here string fd */
- X
- Xint getherestr(fn) /**/
- Xstruct redir *fn;
- X{
- XLklist fake;
- Xchar *s = gettemp(),*t;
- Xint fd;
- X
- X fake = newlist();
- X addnode(fake,fn->name);
- X prefork(fake);
- X if (!errflag)
- X postfork(fake,1);
- X if (errflag)
- X return -1;
- X if ((fd = open(s,O_CREAT|O_WRONLY,0600)) == -1)
- X return -1;
- X while (t = ugetnode(fake))
- X {
- X untokenize(t);
- X write(fd,t,strlen(t));
- X if (full(fake))
- X write(fd," ",1);
- X }
- X write(fd,"\n",1);
- X close(fd);
- X fd = open(s,O_RDONLY);
- X unlink(s);
- X return fd;
- X}
- X
- Xvoid catproc(mn) /**/
- Xstruct multio *mn;
- X{
- Xint len,t0;
- Xchar *buf;
- X
- X if (phork())
- X {
- X for (t0 = 0; t0 != mn->ct; t0++)
- X close(mn->fds[t0]);
- X close(mn->pipe);
- X return;
- X }
- X closeallelse(mn);
- X buf = zalloc(4096);
- X for (t0 = 0; t0 != mn->ct; t0++)
- X while (len = read(mn->fds[t0],buf,4096))
- X write(mn->pipe,buf,len);
- X _exit(0);
- X}
- X
- Xvoid teeproc(mn) /**/
- Xstruct multio *mn;
- X{
- Xint len,t0;
- Xchar *buf;
- X
- X if (phork())
- X {
- X for (t0 = 0; t0 != mn->ct; t0++)
- X close(mn->fds[t0]);
- X close(mn->pipe);
- X return;
- X }
- X buf = zalloc(4096);
- X closeallelse(mn);
- X while ((len = read(mn->pipe,buf,4096)) > 0)
- X for (t0 = 0; t0 != mn->ct; t0++)
- X write(mn->fds[t0],buf,len);
- X _exit(0);
- X}
- X
- Xvoid closeallelse(mn) /**/
- Xstruct multio *mn;
- X{
- Xint t0,t1;
- X
- X for (t0 = 0; t0 != NOFILE; t0++)
- X if (mn->pipe != t0)
- X {
- X for (t1 = 0; t1 != mn->ct; t1++)
- X if (mn->fds[t1] == t0)
- X break;
- X if (t1 == mn->ct)
- X close(t0);
- X }
- X}
- X
- Xlong int zstrtol(s,t,base) /**/
- Xchar *s;char **t;int base;
- X{
- Xint ret = 0;
- X
- X if (base <= 10)
- X for (; *s >= '0' && *s < ('0'+base); s++)
- X ret = ret*base+*s-'0';
- X else
- X for (; idigit(*s) || (*s >= 'a' && *s < ('a'+base-10))
- X || (*s >= 'A' && *s < ('A'+base-10)); s++)
- X ret = ret*base+(idigit(*s) ? (*s-'0') : (*s & 0x1f)+9);
- X if (t)
- X *t = (char *) s;
- X return ret;
- X}
- X
- X/* $(...) */
- X
- XLklist getoutput(cmd,qt) /**/
- Xchar *cmd;int qt;
- X{
- XList list;
- Xint pipes[2];
- X
- X if (*cmd == '<')
- X {
- X int stream;
- X char *fi,*s,x;
- X
- X for (cmd++; *cmd == ' '; cmd++);
- X for (s = cmd; *s && *s != ' '; s++)
- X if (*s == '\\') s++;
- X else if (*s == '$') *s = String;
- X x = *s;
- X *s = '\0';
- X fi = strdup(cmd);
- X *s = x;
- X if (*fi == '~')
- X *fi = Tilde;
- X else if (*fi == '=')
- X *fi = Equals;
- X singsub(&fi);
- X if (errflag)
- X return NULL;
- X stream = open(fi,O_RDONLY);
- X if (stream == -1)
- X {
- X zerr("%e: %s",cmd+1,errno);
- X return NULL;
- X }
- X return readoutput(stream,qt);
- X }
- X if (!(list = parselstring(cmd)))
- X return NULL;
- X mpipe(pipes);
- X if (phork())
- X {
- X popheap();
- X close(pipes[1]);
- X /* chldsuspend(); */
- X return readoutput(pipes[0],qt);
- X }
- X subsh = 1;
- X close(pipes[0]);
- X redup(pipes[1],1);
- X entersubsh(0);
- X signal(SIGTSTP,SIG_IGN);
- X exiting = 1;
- X execlist(list);
- X close(1);
- X exit(0); return NULL;
- X}
- X
- X/* read output of command substitution */
- X
- XLklist readoutput(in,qt) /**/
- Xint in;int qt;
- X{
- XLklist ret;
- Xchar *buf,*ptr;
- Xint bsiz,c,cnt = 0;
- XFILE *fin;
- X
- X fin = fdopen(in,"r");
- X ret = newlist();
- X ptr = buf = zalloc(bsiz = 256);
- X while ((c = fgetc(fin)) != EOF)
- X if (!qt && isep(c))
- X {
- X if (cnt)
- X {
- X *ptr = '\0';
- X addnode(ret,ztrdup(buf));
- X cnt = 0;
- X ptr = buf;
- X }
- X }
- X else
- X {
- X *ptr++ = c;
- X if (++cnt == bsiz)
- X {
- X char *pp = zalloc(bsiz *= 2);
- X
- X memcpy(pp,buf,cnt);
- X free(buf);
- X ptr = (buf = pp)+cnt;
- X }
- X }
- X if (ptr != buf && ptr[-1] == '\n')
- X ptr[-1] = '\0';
- X else
- X *ptr = '\0';
- X if (cnt)
- X addnode(ret,ztrdup(buf));
- X free(buf);
- X fclose(fin);
- X return ret;
- X}
- X
- X/* =(...) */
- X
- Xchar *getoutputfile(cmd) /**/
- Xchar *cmd;
- X{
- X#ifdef WAITPID
- Xint pid;
- X#endif
- Xchar *nam = gettemp(),*str;
- Xint tfil;
- XList list;
- X
- X if (thisjob == -1)
- X return NULL;
- X for (str = cmd; *str && *str != Outpar; str++);
- X if (!*str)
- X zerr("oops.",NULL,0);
- X *str = '\0';
- X if (!(list = parselstring(cmd)))
- X return NULL;
- X permalloc();
- X if (!jobtab[thisjob].filelist)
- X jobtab[thisjob].filelist = newlist();
- X addnode(jobtab[thisjob].filelist,ztrdup(nam));
- X heapalloc();
- X#ifdef WAITPID
- X if (pid = phork())
- X {
- X popheap();
- X waitpid(pid,NULL,WUNTRACED);
- X return nam;
- X }
- X#else
- X if (waitfork())
- X return nam;
- X#endif
- X subsh = 1;
- X close(1);
- X entersubsh(0);
- X tfil = creat(nam,0666);
- X exiting = 1;
- X execlist(list);
- X close(1);
- X exit(0); return NULL;
- X}
- X
- X/* get a temporary named pipe */
- X
- Xchar *namedpipe() /**/
- X{
- Xchar *tnam = gettemp();
- X
- X mknod(tnam,0010666,0);
- X return tnam;
- X}
- X
- X/* <(...) */
- X
- Xchar *getoutproc(cmd) /**/
- Xchar *cmd;
- X{
- XList list;
- Xint fd;
- Xchar *pnam,*str;
- X
- X if (thisjob == -1)
- X return NULL;
- X for (str = cmd; *str && *str != Outpar; str++);
- X if (!*str)
- X zerr("oops.",NULL,0);
- X *str = '\0';
- X pnam = namedpipe();
- X permalloc();
- X if (!jobtab[thisjob].filelist)
- X jobtab[thisjob].filelist = newlist();
- X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
- X heapalloc();
- X if (!(list = parselstring(cmd)))
- X return NULL;
- X if (phork())
- X {
- X popheap();
- X return pnam;
- X }
- X entersubsh(1);
- X fd = open(pnam,O_WRONLY);
- X if (fd == -1)
- X {
- X zerr("can't open %s: %e",pnam,errno);
- X _exit(0);
- X }
- X redup(fd,1);
- X fd = open("/dev/null",O_RDONLY);
- X redup(fd,0);
- X exiting = 1;
- X execlist(list);
- X close(1);
- X _exit(0); return NULL;
- X}
- X
- X/* >(...) */
- X
- Xchar *getinproc(cmd) /**/
- Xchar *cmd;
- X{
- XList list;
- Xint pid,fd;
- Xchar *pnam,*str;
- X
- X if (thisjob == -1)
- X return NULL;
- X for (str = cmd; *str && *str != Outpar; str++);
- X if (!*str)
- X zerr("oops.",NULL,0);
- X *str = '\0';
- X pnam = namedpipe();
- X permalloc();
- X if (!jobtab[thisjob].filelist)
- X jobtab[thisjob].filelist = newlist();
- X addnode(jobtab[thisjob].filelist,ztrdup(pnam));
- X heapalloc();
- X if (!(list = parselstring(cmd)))
- X return NULL;
- X if (pid = phork())
- X {
- X popheap();
- X return pnam;
- X }
- X entersubsh(1);
- X fd = open(pnam,O_RDONLY);
- X redup(fd,0);
- X exiting = 1;
- X execlist(list);
- X _exit(0); return NULL;
- X}
- X
- X/* > >(...) (does not use named pipes) */
- X
- Xint getinpipe(cmd) /**/
- Xchar *cmd;
- X{
- XList list;
- Xint pipes[2];
- Xchar *str = cmd;
- X
- X for (str = cmd; *str && *str != Outpar; str++);
- X if (!*str)
- X zerr("oops.",NULL,0);
- X *str = '\0';
- X if (!(list = parselstring(cmd+2)))
- X return -1;
- X mpipe(pipes);
- X if (phork())
- X {
- X popheap();
- X close(pipes[1]);
- X return pipes[0];
- X }
- X close(pipes[0]);
- X entersubsh(1);
- X redup(pipes[1],1);
- X exiting = 1;
- X execlist(list);
- X _exit(0); return 0;
- X}
- X
- X/* < <(...) */
- X
- Xint getoutpipe(cmd) /**/
- Xchar *cmd;
- X{
- XList list;
- Xint pipes[2];
- Xchar *str;
- X
- X for (str = cmd; *str && *str != Outpar; str++);
- X if (!*str)
- X zerr("oops.",NULL,0);
- X *str = '\0';
- X if (!(list = parselstring(cmd+2)))
- X return -1;
- X strinend();
- X mpipe(pipes);
- X if (phork())
- X {
- X popheap();
- X close(pipes[0]);
- X return pipes[1];
- X }
- X close(pipes[1]);
- X entersubsh(1);
- X redup(pipes[0],0);
- X exiting = 1;
- X execlist(list);
- X _exit(0); return 0;
- X}
- X
- X/* run a list, saving the current job num */
- X
- Xvoid runlist(l) /**/
- XList l;
- X{
- Xint cj = thisjob;
- X
- X execlist(l);
- X thisjob = cj;
- X}
- X
- Xchar *gettemp() /**/
- X{
- X return mktemp(dyncat(tmpprefix,"XXXXXX"));
- X}
- X
- X/* my getwd; all the other ones I tried confused the SIGCHLD handler */
- X
- Xchar *zgetwd() /**/
- X{
- Xstatic char buf0[MAXPATHLEN];
- Xchar buf3[MAXPATHLEN],*buf2 = buf0+1;
- Xstruct stat sbuf;
- Xstruct direct *de;
- XDIR *dir;
- Xino_t ino = -1;
- Xdev_t dev = -1;
- X
- X holdintr();
- X buf2[0] = '\0';
- X buf0[0] = '/';
- X for(;;)
- X {
- X if (stat(".",&sbuf) < 0)
- X {
- X chdir(buf0);
- X noholdintr();
- X return ztrdup(".");
- X }
- X ino = sbuf.st_ino;
- X dev = sbuf.st_dev;
- X if (stat("..",&sbuf) < 0)
- X {
- X chdir(buf0);
- X noholdintr();
- X return ztrdup(".");
- X }
- X if (sbuf.st_ino == ino && sbuf.st_dev == dev)
- X {
- X chdir(buf0);
- X noholdintr();
- X return ztrdup(buf0);
- X }
- X dir = opendir("..");
- X if (!dir)
- X {
- X chdir(buf0);
- X noholdintr();
- X return ztrdup(".");
- X }
- X chdir("..");
- X readdir(dir); readdir(dir);
- X while (de = readdir(dir))
- X if (de->d_ino == ino)
- X {
- X lstat(de->d_name,&sbuf);
- X if (sbuf.st_dev == dev)
- X goto match;
- X }
- X rewinddir(dir);
- X readdir(dir); readdir(dir);
- X while (de = readdir(dir))
- X {
- X lstat(de->d_name,&sbuf);
- X if (sbuf.st_dev == dev)
- X goto match;
- X }
- X noholdintr();
- X closedir(dir);
- X return ztrdup(".");
- Xmatch:
- X strcpy(buf3,de->d_name);
- X if (*buf2)
- X strcat(buf3,"/");
- X strcat(buf3,buf2);
- X strcpy(buf2,buf3);
- X closedir(dir);
- X }
- X}
- X
- X/* open pipes with fds >= 10 */
- X
- Xvoid mpipe(pp) /**/
- Xint *pp;
- X{
- X pipe(pp);
- X pp[0] = movefd(pp[0]);
- X pp[1] = movefd(pp[1]);
- X}
- X
- X/* do process substitution with redirection */
- X
- Xvoid spawnpipes(l) /**/
- XLklist l;
- X{
- XLknode n = firstnode(l);
- XRedir f;
- X
- X for (; n; incnode(n))
- X {
- X f = (Redir) getdata(n);
- X if (f->type == OUTPIPE)
- X {
- X char *str = f->name;
- X f->fd2 = getoutpipe(str);
- X }
- X if (f->type == INPIPE)
- X {
- X char *str = f->name;
- X f->fd2 = getinpipe(str);
- X }
- X }
- X}
- X
- X/* perform time ... command */
- X
- Xint exectime(cmd) /**/
- XCmd cmd;
- X{
- Xint jb = thisjob;
- X
- X execpline(cmd->u.pline,TIMED,0);
- X thisjob = jb;
- X return lastval;
- X}
- X
- X/* define a function */
- X
- Xint execfuncdef(cmd) /**/
- XCmd cmd;
- X{
- XCmdnam cc;
- Xchar *s;
- X
- X permalloc();
- X while (s = ugetnode(cmd->args))
- X {
- X cc = (Cmdnam) zalloc(sizeof *cc);
- X cc->type = SHFUNC;
- X cc->flags = 0;
- X if (!cmd->u.list)
- X cc->u.list = NULL;
- X else
- X cc->u.list = (List) dupstruct(cmd->u.list);
- X addhnode(ztrdup(s),cc,cmdnamtab,freecmdnam);
- X if (!strncmp(s,"TRAP",4))
- X {
- X int t0 = getsignum(s+4);
- X
- X if (t0 != -1)
- X settrap(t0,cmd->u.list);
- X }
- X }
- X heapalloc();
- X return 0;
- X}
- X
- X/* evaluate a [[ ... ]] */
- X
- Xint execcond(cmd) /**/
- XCmd cmd;
- X{
- X return !evalcond(cmd->u.cond);
- X}
- X
- Xvoid execshfunc(cmd,cn) /**/
- XCmd cmd;Cmdnam cn;
- X{
- Xchar **tab,**x,*oargv0;
- Xint oxtr = opts[XTRACE],flags,xexittr;
- XList l;
- XLklist olist;
- Xchar *s;
- XList xexitfn;
- X
- X if (errflag)
- X return;
- X l = cn->u.list;
- X if (!l)
- X {
- X char *nam;
- X
- X if (!(l = getfpfunc(nam = peekfirst(cmd->args))))
- X {
- X zerr("function not found: %s",nam,0);
- X lastval = 1;
- X return;
- X }
- X cn->flags &= ~PMFLAG_u;
- X permalloc();
- X cn->u.list = (List) dupstruct(l);
- X heapalloc();
- X }
- X flags = cn->flags;
- X xexittr = sigtrapped[SIGEXIT];
- X xexitfn = sigfuncs[SIGEXIT];
- X tab = pparams;
- X oargv0 = argzero;
- X optind = 0;
- X if (flags & PMFLAG_t)
- X opts[XTRACE] = OPT_SET;
- X pparams = x = (char **) zcalloc(((sizeof *x)*(1+countnodes(cmd->args))));
- X argzero = ztrdup(ugetnode(cmd->args));
- X while (*x = ugetnode(cmd->args))
- X *x = ztrdup(*x), x++;
- X permalloc();
- X olist = locallist;
- X locallist = newlist();
- X heapalloc();
- X newrunlist(l);
- X while (s = getnode(locallist))
- X unsetparam(s);
- X free(locallist);
- X locallist = olist;
- X retflag = 0;
- X cmd->u.list = NULL;
- X freearray(pparams);
- X free(argzero);
- X argzero = oargv0;
- X pparams = tab;
- X if (sigfuncs[SIGEXIT] && sigfuncs[SIGEXIT] != xexitfn)
- X {
- X dotrap(SIGEXIT);
- X freestruct(sigfuncs[SIGEXIT]);
- X }
- X sigtrapped[SIGEXIT] = xexittr;
- X sigfuncs[SIGEXIT] = xexitfn;
- X opts[XTRACE] = oxtr;
- X}
- X
- X/* search fpath for an undefined function */
- X
- XList getfpfunc(s) /**/
- Xchar *s;
- X{
- Xchar **pp = fpath,buf[MAXPATHLEN];
- Xint fd;
- X
- X for (; *pp; pp++)
- X {
- X sprintf(buf,"%s/%s",*pp,s);
- X if (!access(buf,R_OK) && (fd = open(buf,O_RDONLY)) != -1)
- X {
- X int len = lseek(fd,0,2);
- X
- X if (len == -1)
- X close(fd);
- X else
- X {
- X char *d;
- X
- X lseek(fd,0,0);
- X d = zcalloc(len+1);
- X if (read(fd,d,len) != len)
- X {
- X free(d);
- X close(fd);
- X }
- X else
- X {
- X close(fd);
- X return parselstring(d);
- X }
- X }
- X }
- X }
- X return NULL;
- X}
- X
- X/* check to see if AUTOCD applies here */
- X
- Xint cancd(s)
- Xchar *s;
- X{
- X if (*s != '/')
- X {
- X char sbuf[MAXPATHLEN],**cp;
- X
- X if (cancd2(s))
- X return 1;
- X if (access(s,X_OK) == 0)
- X return 0;
- X for (cp = cdpath; *cp; cp++)
- X {
- X sprintf(sbuf,"%s/%s",*cp,s);
- X if (cancd2(sbuf))
- X return 1;
- X }
- X return 0;
- X }
- X return cancd2(s);
- X}
- X
- Xint cancd2(s)
- Xchar *s;
- X{
- Xstruct stat buf;
- X
- X return !(access(s,X_OK) || stat(s,&buf) || !S_ISDIR(buf.st_mode));
- X}
- X
- SHAR_EOF
- echo 'File zsh2.1/src/exec.c is complete' &&
- chmod 0644 zsh2.1/src/exec.c ||
- echo 'restore of zsh2.1/src/exec.c failed'
- Wc_c="`wc -c < 'zsh2.1/src/exec.c'`"
- test 33003 -eq "$Wc_c" ||
- echo 'zsh2.1/src/exec.c: original size 33003, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= zsh2.1/src/funcs.h ==============
- if test -f 'zsh2.1/src/funcs.h' -a X"$1" != X"-c"; then
- echo 'x - skipping zsh2.1/src/funcs.h (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting zsh2.1/src/funcs.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/funcs.h' &&
- Xstruct asgment;
- Xstruct utmp;
- X
- X#include "builtin.pro"
- X#include "cond.pro"
- X#include "exec.pro"
- X#include "glob.pro"
- X#include "hist.pro"
- X#include "init.pro"
- X#include "jobs.pro"
- X#include "lex.pro"
- X#include "loop.pro"
- X#include "math.pro"
- X#include "mem.pro"
- X#include "params.pro"
- X#include "parse.pro"
- X#include "subst.pro"
- X#include "table.pro"
- X#include "text.pro"
- X#include "utils.pro"
- X#include "watch.pro"
- X#include "zle_hist.pro"
- X#include "zle_main.pro"
- X#include "zle_misc.pro"
- X#include "zle_move.pro"
- X#include "zle_refresh.pro"
- X#include "zle_tricky.pro"
- X#include "zle_utils.pro"
- X#include "zle_vi.pro"
- X#include "zle_word.pro"
- X
- Xchar *mktemp DCLPROTO((char *));
- Xchar *malloc DCLPROTO((int));
- X#ifndef __STDC__
- Xchar *realloc DCLPROTO((char *,int));
- Xchar *calloc DCLPROTO((int,int));
- X#endif /* __STDC__ */
- Xchar *ttyname DCLPROTO((int));
- X
- Xextern char PC, *BC, *UP;
- Xextern short ospeed;
- Xextern int tgetent DCLPROTO((char *bp, char *name));
- Xextern int tgetnum DCLPROTO((char *id));
- Xextern int tgetflag DCLPROTO((char *id));
- Xextern char *tgetstr DCLPROTO((char *id, char **area));
- Xextern char *tgoto DCLPROTO((char *cm, int destcol, int destline));
- Xextern int tputs DCLPROTO((char *cp, int affcnt, int (*outc)()));
- SHAR_EOF
- chmod 0644 zsh2.1/src/funcs.h ||
- echo 'restore of zsh2.1/src/funcs.h failed'
- Wc_c="`wc -c < 'zsh2.1/src/funcs.h'`"
- test 1198 -eq "$Wc_c" ||
- echo 'zsh2.1/src/funcs.h: original size 1198, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= zsh2.1/src/glob.c ==============
- if test -f 'zsh2.1/src/glob.c' -a X"$1" != X"-c"; then
- echo 'x - skipping zsh2.1/src/glob.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting zsh2.1/src/glob.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'zsh2.1/src/glob.c' &&
- X/*
- X
- X glob.c - filename generation
- X
- X This file is part of zsh, the Z shell.
- X
- X zsh is free software; no one can prevent you from reading the source
- X code, or giving it to someone else.
- X
- X This file is copyrighted under the GNU General Public License, which
- X can be found in the file called COPYING.
- X
- X Copyright (C) 1990, 1991 Paul Falstad
- X
- X zsh is distributed in the hope that it will be useful, but
- X WITHOUT ANY WARRANTY. No author or distributor accepts
- X responsibility to anyone for the consequences of using it or for
- X whether it serves any particular purpose or works at all, unless he
- X says so in writing. Refer to the GNU General Public License
- X for full details.
- X
- X Everyone is granted permission to copy, modify and redistribute
- X zsh, but only under the conditions described in the GNU General Public
- X License. A copy of this license is supposed to have been given to you
- X along with zsh so you can know your rights and responsibilities.
- X It should be in a file named COPYING.
- X
- X Among other things, the copyright notice and this notice must be
- X preserved on all copies.
- X
- X*/
- X
- X#include "zsh.h"
- X
- X#ifdef __hpux
- X#include <ndir.h>
- X#else
- X#ifdef SYSV
- X#define direct dirent
- X#else
- X#include <sys/dir.h>
- X#endif
- X#endif
- X#include <sys/errno.h>
- X
- X#define exists(X) (access(X,0) == 0)
- X
- Xstatic int mode; /* != 0 if we are parsing glob patterns */
- Xstatic int pathpos; /* position in pathbuf */
- Xstatic int matchsz; /* size of matchbuf */
- Xstatic int matchct; /* number of matches found */
- Xstatic char pathbuf[MAXPATHLEN]; /* pathname buffer */
- Xstatic char **matchbuf; /* array of matches */
- Xstatic char **matchptr; /* &matchbuf[matchct] */
- X
- X/* max # of qualifiers */
- X
- X#define QUALCT 16
- X
- Xstatic int (*qualfuncs[QUALCT])DCLPROTO((struct stat *,long));
- Xstatic long qualdata[QUALCT];
- Xstatic int qualsense[QUALCT];
- Xstatic int qualct;
- X
- X/* pathname component in filename patterns */
- X
- Xstruct complist {
- X Complist next;
- X Comp comp;
- X int closure; /* 1 if this is a (foo/)# */
- X };
- Xstruct comp {
- X Comp left,right,next;
- X char *str;
- X int closure,last;
- X };
- X
- Xvoid glob(list,np) /**/
- XLklist list;Lknode *np;
- X{
- XLknode node = prevnode(*np);
- XLknode next = nextnode(*np);
- Xint sl; /* length of the pattern */
- Xchar *ostr; /* the pattern before the parser chops it up */
- XComplist q; /* pattern after parsing */
- Xchar *str = getdata(*np); /* the pattern */
- X
- X sl = strlen(str);
- X ostr = strdup(str);
- X uremnode(list,*np);
- X qualct = 0;
- X if (str[sl-1] == Outpar) /* check for qualifiers */
- X {
- X char *s;
- X int sense = 0;
- X long data;
- X int (*func) DCLPROTO((struct stat *,long));
- X
- X for (s = str+sl-2; s != str; s--)
- X if (*s == Bar || *s == Outpar || *s == Inpar)
- X break;
- X if (*s == Inpar)
- X {
- X *s++ = '\0';
- X func = NULL;
- X while (*s != Outpar)
- X {
- X func = NULL;
- X if (idigit(*s))
- X {
- X func = qualflags;
- X data = 0;
- X while (idigit(*s))
- X data = data*010+(*s++-'0');
- X }
- X else switch (*s++)
- X {
- X case Hat: case '^': sense = 1-sense; break;
- X#ifdef S_IFLNK
- X case '@': func = qualmode; data = S_IFLNK; break;
- X#endif
- X#ifdef S_IFSOCK
- X case '=': func = qualmode; data = S_IFSOCK; break;
- X#endif
- X#ifdef S_IFIFO
- X case 'p': func = qualmode; data = S_IFIFO; break;
- X#endif
- X case '/': func = qualmode; data = S_IFDIR; break;
- X case '.': func = qualmode; data = S_IFREG; break;
- X case '%': func = qualisdev; break;
- X case Star: func = qualiscom; break;
- X case 'R': func = qualflags; data = 0004; break;
- X case 'W': func = qualflags; data = 0002; break;
- X case 'X': func = qualflags; data = 0001; break;
- X case 'r': func = qualflags; data = 0400; break;
- X case 'w': func = qualflags; data = 0200; break;
- X case 'x': func = qualflags; data = 0100; break;
- X case 's': func = qualflags; data = 04000; break;
- X case 'S': func = qualflags; data = 02000; break;
- X case 'd': func = qualdev; data = qgetnum(&s); break;
- X case 'l': func = qualnlink; data = qgetnum(&s); break;
- X case 'U': func = qualuid; data = geteuid(); break;
- X case 'G': func = qualgid; data = getegid(); break;
- X case 'u': func = qualuid; data = qgetnum(&s); break;
- X case 'g': func = qualgid; data = qgetnum(&s); break;
- X default: zerr("unknown file attribute",NULL,0); return;
- X }
- X if (func)
- X {
- X if (qualct == QUALCT-1)
- X {
- X zerr("too many qualifiers",NULL,0);
- X return;
- X }
- X qualfuncs[qualct] = func;
- X qualsense[qualct] = sense;
- X qualdata[qualct] = data;
- X qualct++;
- X }
- X if (errflag)
- X return;
- X }
- X }
- X }
- X else if (str[sl-1] == '/') /* foo/ == foo(/) */
- X {
- X str[sl-1] = '\0';
- X qualfuncs[0] = qualmode;
- X qualdata[0] = S_IFDIR;
- X qualsense[0] = 0;
- X qualct = 1;
- X }
- X qualfuncs[qualct] = NULL;
- X if (*str == '/') /* pattern has absolute path */
- X {
- X str++;
- X pathbuf[0] = '/';
- X pathbuf[pathpos = 1] = '\0';
- X }
- X else /* pattern is relative to cwd */
- X pathbuf[pathpos = 0] = '\0';
- X q = parsepat(str);
- X if (!q || errflag) /* if parsing failed */
- X {
- X if (isset(NOBADPATTERN))
- X {
- X insnode(list,node,ostr);
- X return;
- X }
- X errflag = 0;
- X zerr("bad pattern: %s",ostr,0);
- X return;
- X }
- X matchptr = matchbuf = (char **) zalloc((matchsz = 16)*sizeof(char *));
- X matchct = 0;
- X scanner(q); /* do the globbing */
- X if (matchct)
- X badcshglob |= 2;
- X else if (unset(NULLGLOB))
- X if (isset(CSHNULLGLOB)) {
- X badcshglob |= 1;
- X } else if (unset(NONOMATCH)) {
- X zerr("no matches found: %s",ostr,0);
- X free(matchbuf);
- X return;
- X } else {
- X *matchptr++ = strdup(ostr);
- X matchct = 1;
- X }
- X qsort(&matchbuf[0],matchct,sizeof(char *),notstrcmp);
- X matchptr = matchbuf;
- X while (matchct--) /* insert matches in the arg list */
- X insnode(list,node,*matchptr++);
- X free(matchbuf);
- X *np = (next) ? prevnode(next) : lastnode(list);
- X}
- X
- X/* get number after qualifier */
- X
- Xlong qgetnum(s) /**/
- Xchar **s;
- X{
- Xlong v = 0;
- X
- X if (!idigit(**s))
- X {
- X zerr("number expected",NULL,0);
- X return 0;
- X }
- X while (idigit(**s))
- X v = v*10+*(*s)++-'0';
- X return v;
- X}
- X
- Xint notstrcmp(a,b) /**/
- Xchar **a;char **b;
- X{
- Xchar *c = *b,*d = *a;
- Xint x1,x2;
- X
- X for (; *c == *d && *c; c++,d++);
- X x1 = atoi(c); x2 = atoi(d);
- X if (x1==x2)
- X return ((int) (unsigned char) *c-(int) (unsigned char) *d);
- X return x1-x2;
- X}
- X
- Xint forstrcmp(a,b) /**/
- Xchar **a;char **b;
- X{
- Xchar *c = *b,*d = *a;
- X
- X for (; *c == *d && *c; c++,d++);
- X return ((int) (unsigned char) *d-(int) (unsigned char) *c);
- X}
- X
- X/* add a match to the list */
- X
- Xvoid insert(s) /**/
- Xchar *s;
- X{
- Xstruct stat buf;
- X
- X if (isset(MARKDIRS) && !lstat(s,&buf) && S_ISDIR(buf.st_mode)) /* grrr */
- X {
- X char *t;
- X int ll = strlen(s);
- X
- X t = ncalloc(ll+2);
- X strcpy(t,s);
- X t[ll] = '/';
- X t[ll+1] = '\0';
- X s = t;
- X }
- X *matchptr++ = s;
- X if (++matchct == matchsz)
- X {
- X matchbuf = (char **) realloc((char *) matchbuf,
- X sizeof(char **)*(matchsz *= 2));
- X matchptr = matchbuf+matchct;
- X }
- X}
- X
- X/* check to see if str is eligible for filename generation */
- X
- Xint haswilds(str) /**/
- Xchar *str;
- X{
- X if (!str[1] && (*str == Inbrack || *str == Outbrack))
- X return 0;
- X if (str[0] == '%')
- X return 0;
- X for (; *str; str++)
- X if (str[0] == Star && str[1] == Star &&
- X str[2] == Star && str[3] == Star && str[4] == '/')
- X return 1;
- X else if (*str == Pound || *str == Hat || *str == Star ||
- X *str == Bar || *str == Inbrack || *str == Inang ||
- X *str == Quest)
- X return 1;
- X return 0;
- X}
- X
- X/* check to see if str is eligible for brace expansion */
- X
- Xint hasbraces(str) /**/
- Xchar *str;
- X{
- Xint mb,bc,cmct1,cmct2;
- Xchar *lbr = NULL;
- X
- X if (str[0] == Inbrace && str[1] == Outbrace)
- X return 0;
- X for (mb = bc = cmct1 = cmct2 = 0; *str; str++)
- X {
- X if (*str == Inbrace)
- X {
- X if (!bc)
- X lbr = str;
- X bc++;
- X if (str[4] == Outbrace && str[2] == '-') /* {a-z} */
- X {
- X cmct1++;
- X if (bc == 1)
- X cmct2++;
- X }
- X }
- X else if (*str == Outbrace)
- X {
- X bc--;
- X if (!bc)
- X {
- X if (!cmct2)
- X {
- X *lbr = '{';
- X *str = '}';
- X }
- X cmct2 = 0;
- X }
- X }
- X else if (*str == Comma && bc)
- X {
- X cmct1++;
- X if (bc == 1)
- X cmct2++;
- X }
- X if (bc > mb)
- X mb = bc;
- X if (bc < 0)
- X return 0;
- X }
- X return (mb && bc == 0 && cmct1);
- X}
- X
- X/* expand stuff like >>*.c */
- X
- Xint xpandredir(fn,tab) /**/
- Xstruct redir *fn;Lklist tab;
- X{
- XLklist fake;
- Xchar *nam;
- Xstruct redir *ff;
- Xint ret = 0;
- X
- X fake = newlist();
- X addnode(fake,fn->name);
- X prefork(fake);
- X if (!errflag)
- X postfork(fake,1);
- X if (errflag)
- X return 0;
- X if (full(fake) && !nextnode(firstnode(fake)))
- X {
- X fn->name = peekfirst(fake);
- X untokenize(fn->name);
- X }
- X else
- X while (nam = ugetnode(fake))
- X {
- X ff = alloc(sizeof *ff);
- X *ff = *fn;
- X ff->name = nam;
- X addnode(tab,ff);
- X ret = 1;
- X }
- X return ret;
- X}
- X
- X/* concatenate s1 and s2 in dynamically allocated buffer */
- X
- Xchar *dyncat(s1,s2) /**/
- Xchar *s1;char *s2;
- X{
- Xchar *ptr;
- X
- X ptr = ncalloc(strlen(s1)+strlen(s2)+1);
- X strcpy(ptr,s1);
- X strcat(ptr,s2);
- X return ptr;
- X}
- X
- X/* concatenate s1, s2, and s3 in dynamically allocated buffer */
- X
- Xchar *tricat(s1,s2,s3) /**/
- Xchar *s1;char *s2;char *s3;
- X{
- Xchar *ptr;
- X
- X ptr = zalloc(strlen(s1)+strlen(s2)+strlen(s3)+1);
- X strcpy(ptr,s1);
- X strcat(ptr,s2);
- X strcat(ptr,s3);
- X return ptr;
- X}
- X
- X/* brace expansion */
- X
- Xvoid xpandbraces(list,np) /**/
- XLklist list;Lknode *np;
- X{
- XLknode node = (*np),last = prevnode(node);
- Xchar *str = getdata(node),*str3 = str,*str2;
- Xint prev;
- X
- X for (; *str != Inbrace; str++);
- X if (str[2] == '-' && str[4] == Outbrace) /* {a-z} */
- X {
- X char c1,c2;
- X
- X uremnode(list,node);
- X chuck(str);
- X c1 = *str;
- X chuck(str);
- X chuck(str);
- X c2 = *str;
- X chuck(str);
- X if (itok(c1))
- X c1 = ztokens[c1-Pound];
- X if (itok(c2))
- X c2 = ztokens[c2-Pound];
- X if (c1 < c2)
- X for (; c2 >= c1; c2--) /* {a-z} */
- X {
- X *str = c2;
- X insnode(list,last,strdup(str3));
- X }
- X else
- X for (; c2 <= c1; c2++) /* {z-a} */
- X {
- X *str = c2;
- X insnode(list,last,strdup(str3));
- X }
- X *np = nextnode(last);
- X return;
- X }
- X prev = str-str3;
- X str2 = getparen(str++);
- X if (!str2)
- X {
- X zerr("how did you get this error?",NULL,0);
- X return;
- X }
- X uremnode(list,node);
- X node = last;
- X for(;;)
- X {
- X char *zz,*str4;
- X int cnt;
- X
- X for (str4 = str, cnt = 0; cnt || *str != Comma && *str !=
- X Outbrace; str++)
- X if (*str == Inbrace)
- X cnt++;
- X else if (*str == Outbrace)
- X cnt--;
- X else if (!*str)
- X exit(10);
- X zz = zalloc(prev+(str-str4)+strlen(str2)+1);
- X ztrncpy(zz,str3,prev);
- X strncat(zz,str4,str-str4);
- X strcat(zz,str2);
- X insnode(list,node,zz);
- X incnode(node);
- X if (*str != Outbrace)
- X str++;
- X else
- X break;
- X }
- X *np = nextnode(last);
- X}
- X
- X/* get closing paren, given pointer to opening paren */
- X
- Xchar *getparen(str) /**/
- Xchar *str;
- X{
- Xint cnt = 1;
- Xchar typein = *str++,typeout = typein+1;
- X
- X for (; *str && cnt; str++)
- X if (*str == typein)
- X cnt++;
- X else if (*str == typeout)
- X cnt--;
- X if (!str && cnt)
- X return NULL;
- X return str;
- X}
- X
- X/* check to see if a matches b (b is not a filename pattern) */
- X
- Xint matchpat(a,b) /**/
- Xchar *a;char *b;
- X{
- XComp c;
- Xint val,len;
- Xchar *b2;
- X
- X remnulargs(b);
- X len = strlen(b);
- X b2 = alloc(len+3);
- X strcpy(b2+1,b);
- X b2[0] = Inpar;
- X b2[len+1] = Outpar;
- X b2[len+2] = '\0';
- X c = parsereg(b2);
- X if (!c)
- X {
- X zerr("bad pattern: %s",b,0);
- X return 0;
- X }
- X val = domatch(a,c,0);
- X return val;
- X}
- X
- X/* do the ${foo%%bar}, ${foo#bar} stuff */
- X/* please do not laugh at this code. */
- X
- Xvoid getmatch(sp,pat,dd) /**/
- Xchar **sp;char *pat;int dd;
- X{
- XComp c;
- Xchar *t,*lng = NULL,cc,*s = *sp;
- X
- X remnulargs(pat);
- X c = parsereg(pat);
- X if (!c)
- X {
- X zerr("bad pattern: %s",pat,0);
- X return;
- X }
- X if (!(dd & 2))
- X {
- X for (t = s; t==s || t[-1]; t++)
- X {
- X cc = *t;
- X *t = '\0';
- X if (domatch(s,c,0))
- X {
- X if (!(dd & 1))
- X {
- X *t = cc;
- X t = strdup(t);
- X *sp = t;
- X return;
- X }
- X lng = t;
- X }
- X *t = cc;
- X }
- X if (lng)
- X {
- X t = strdup(lng);
- X *sp = t;
- X return;
- X }
- X }
- X else
- X {
- X for (t = s+strlen(s); t >= s; t--)
- X {
- X if (domatch(t,c,0))
- X {
- X if (!(dd & 1))
- X {
- X cc = *t;
- X *t = '\0';
- X *sp = strdup(*sp);
- X *t = cc;
- X return;
- X }
- X lng = t;
- X }
- X }
- X if (lng)
- X {
- X cc = *lng;
- X *lng = '\0';
- X *sp = strdup(*sp);
- X *lng = cc;
- X return;
- X }
- X }
- X}
- X
- X/* add a component to pathbuf */
- X
- Xstatic int addpath(s)
- Xchar *s;
- X{
- X if (strlen(s)+pathpos >= MAXPATHLEN) return 0;
- X while (pathbuf[pathpos++] = *s++);
- X pathbuf[pathpos-1] = '/';
- X pathbuf[pathpos] = '\0';
- X return 1;
- X}
- X
- Xchar *getfullpath(s) /**/
- Xchar *s;
- X{
- Xstatic char buf[MAXPATHLEN];
- X
- X strcpy(buf,pathbuf);
- X strcat(buf,s);
- X return buf;
- X}
- X
- X/* do the globbing */
- X
- Xvoid scanner(q) /**/
- XComplist q;
- X{
- XComp c;
- Xint closure;
- X
- X if (closure = q->closure) /* (foo/)# */
- X if (q->closure == 2) /* (foo/)## */
- X q->closure = 1;
- X else
- X scanner(q->next);
- X if (c = q->comp)
- X {
- X if (!(c->next || c->left) && !haswilds(c->str))
- X if (q->next)
- X {
- X int oppos = pathpos;
- X
- X if (errflag)
- X return;
- X if (q->closure && !strcmp(c->str,".")) return;
- X if (!addpath(c->str)) return;
- X if (!closure || exists(pathbuf))
- X scanner((q->closure) ? q : q->next);
- X pathbuf[pathpos = oppos] = '\0';
- X }
- X else
- X {
- X char *s;
- X
- X if (exists(s = getfullpath(c->str)))
- X insert(strdup(s));
- X }
- X else
- X {
- X char *fn;
- X int dirs = !!q->next;
- X struct direct *de;
- X DIR *lock = opendir((*pathbuf) ? pathbuf : ".");
- X
- X if (lock == NULL)
- X return;
- X readdir(lock); readdir(lock); /* skip . and .. */
- X while (de = readdir(lock))
- X {
- X if (errflag)
- X break;
- X fn = &de->d_name[0];
- X if (domatch(fn,c,unset(GLOBDOTS)))
- X {
- X int oppos = pathpos;
- X
- X if (dirs)
- X {
- X if (closure)
- X {
- X int type3;
- X struct stat buf;
- X
- X if (lstat(getfullpath(fn),&buf) == -1)
- X {
- X if (errno != ENOENT && errno != EINTR &&
- X errno != ENOTDIR)
- X {
- X zerr("%e: %s",fn,errno);
- X errflag = 0;
- X }
- X continue;
- X }
- X type3 = buf.st_mode & S_IFMT;
- X if (type3 != S_IFDIR)
- X continue;
- X }
- X if (addpath(fn))
- X scanner((q->closure) ? q : q->next); /* scan next level */
- X pathbuf[pathpos = oppos] = '\0';
- X }
- X else
- X {
- X if (qualct) /* do the (X) (^X) stuff */
- X {
- X int (**fptr)DCLPROTO((struct stat *,long)) = qualfuncs;
- X int *sptr = qualsense;
- X long *lptr = qualdata;
- X struct stat buf;
- X
- X if (lstat(getfullpath(fn),&buf) == -1)
- X {
- X if (errno != ENOENT && errno != EINTR)
- X {
- X zerr("%e: %s",fn,errno);
- X errflag = 0;
- X }
- X continue;
- X }
- X while (*fptr)
- X if (!(!!((*fptr++)(&buf,*lptr++)) ^ *sptr++))
- X {
- X fptr = NULL;
- X break;
- X }
- X if (!fptr)
- X continue;
- X }
- X insert(dyncat(pathbuf,fn));
- X }
- X }
- X }
- X closedir(lock);
- X }
- X }
- X else
- X zerr("no idea how you got this error message.",NULL,0);
- X}
- X
- X/* do the [..(foo)..] business */
- X
- Xint minimatch(pat,str) /**/
- Xchar **pat;char **str;
- X{
- Xchar *pt = *pat+1,*s = *str;
- X
- X for (; *pt != Outpar; s++,pt++)
- X if ((*pt != Quest || !*s) && *pt != *s)
- X {
- X *pat = getparen(*pat)-1;
- X return 0;
- X }
- X *str = s-1;
- X return 1;
- X}
- X
- Xstatic char *pptr;
- Xstatic Comp tail = 0;
- Xstatic int first;
- X
- Xint domatch(str,c,fist) /**/
- Xchar *str;Comp c;int fist;
- X{
- X pptr = str;
- X first = fist;
- X return doesmatch(c);
- X}
- X
- X/* see if current pattern matches c */
- X
- Xint doesmatch(c) /**/
- XComp c;
- X{
- Xchar *pat = c->str;
- X
- X if (c->closure == 1)
- X {
- X char *saves = pptr;
- X int savei = first;
- X
- X if (doesmatch(c->next))
- X return 1;
- X pptr = saves;
- X first = savei;
- X }
- X for(;;)
- X {
- X if (!pat || !*pat)
- X {
- X char *saves;
- X int savei;
- X
- X if (errflag)
- X return 0;
- X saves = pptr;
- X savei = first;
- X if (c->left || c->right)
- X if (!doesmatch(c->left))
- X if (c->right)
- X {
- X pptr = saves;
- X first = savei;
- X if (!doesmatch(c->right))
- X return 0;
- X }
- X else
- X return 0;
- X if (c->closure)
- X return doesmatch(c);
- X if (!c->next)
- X return (!c->last || !*pptr);
- X return doesmatch(c->next);
- X }
- X if (first && *pptr == '.' && *pat != '.')
- X return 0;
- X if (*pat == Star) /* final * is not expanded to ?#; returns success */
- X {
- X while (*pptr) pptr++;
- X return 1;
- X }
- X first = 0;
- X if (*pat == Quest && *pptr)
- X {
- X pptr++;
- X pat++;
- X continue;
- X }
- X if (*pat == Hat)
- X return 1-doesmatch(c->next);
- X if (*pat == Inbrack) {
- X if (!*pptr) break;
- X if (pat[1] == Hat || pat[1] == '^') {
- X pat[1] = Hat;
- X for (pat += 2; *pat != Outbrack && *pat; pat++)
- X if (*pat == '-' && pat[-1] != Hat && pat[1] != Outbrack) {
- X if (pat[-1] <= *pptr && pat[1] >= *pptr)
- X break;
- X } else if (*pptr == *pat) break;
- X if (!*pat) {
- X zerr("something is very wrong.",NULL,0);
- X return 0;
- X }
- X if (*pat != Outbrack)
- X break;
- X pat++;
- X pptr++;
- X continue;
- X } else {
- X for (pat++; *pat != Outbrack && *pat; pat++)
- X if (*pat == Inpar) {
- X if (minimatch(&pat,&pptr))
- X break;
- X } else if (*pat == '-' && pat[-1] != Inbrack &&
- X pat[1] != Outbrack) {
- X if (pat[-1] <= *pptr && pat[1] >= *pptr)
- X break;
- X } else if (*pptr == *pat) break;
- X if (!pat || !*pat) {
- X zerr("oh dear. that CAN'T be right.",NULL,0);
- X return 0;
- SHAR_EOF
- true || echo 'restore of zsh2.1/src/glob.c failed'
- fi
- echo 'End of zsh2.1.0 part 6'
- echo 'File zsh2.1/src/glob.c is continued in part 7'
- echo 7 > _shar_seq_.tmp
- exit 0
-
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-